﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Simulatore_0._1
{
    public class Banca
    {
        #region MyRegion

        private ModelloFS2 modello;
        private OrganoDiGoverno odg;
        public double Rd { get; private set; }
        public double leverage { get; private set; }
        public double rendimento { get; private set; }
        public int id { get; private set; }
        public double maxLeverageBank { get; private set; }
        public string type;

        #endregion

        public Banca ( ModelloFS2 modello, OrganoDiGoverno odg, int id, double rendimento, double leverage, string type )
        {
            this.id=id;
            this.modello = modello;
            this.rendimento = rendimento;
            this.leverage = leverage;
            this.odg=odg;
            this.type=type;
        }

        public void behaviour_leader ()
        {
            //controllo aggiuntivo che serve per risolvere questo problema:
            //se la banca nasce inizialmente con un leverage(calcolato Random) > del leverageMax dell'organo di governo...
            //il leverage della banca deve diminuire fino a quando non rientra nei limiti massimi dell'organo di governo.
            //Ovviamente questo discorso ha senso solo se l'organo di governo è attivo
            //La leva diminuisce di MaxLeverageBankLeader o follower o locale
            //Questo discorso è valido anche per gli altri tipi di banca 
            if(leverage>odg.maxLeverageOrganoDiGoverno && odg.check_organoGovernoActive==true)
                leverage= leverage - modello.crescitaLevaMaxStepLeader;
            //Rd=rendimento desiderato dalla banca che vorrebbe raggiungere
            Rd = rendimento + modello.crescitaRendimentoMaxStepLeader;
            Console.WriteLine("{0}", this.ToString());

            //la banca vede se tale rendimento è sostenibile
            //se è sostenibile allora aggiorna il rendimento
            if(Rd <= modello.rendimentoRiskFree + (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) * leverage)
            {
                rendimento = Rd;
                Console.WriteLine("A");
            }
            else
            {
                //L'aumento della leva può essere fatto solo entro un certo limite
                //if((leverage+modello.crescitaLevaMaxStep<modello.maxLeverageBank) ||
                //        (leverage+modello.crescitaLevaMaxStep<modello.maxLeverageOrganoDiGoverno &&
                //         modello.check_organoGovernoActive))
                if(((leverage+modello.crescitaLevaMaxStepLeader)<Math.Min(modello.maxLeverageBankLeader, odg.maxLeverageOrganoDiGoverno) && odg.check_organoGovernoActive) ||
                ((leverage+modello.crescitaLevaMaxStepLeader)<modello.maxLeverageBankLeader) && !odg.check_organoGovernoActive)
                {
                    
                    //altrimenti ricalcolo leva per poterla incrementare in maniera tale da avere un Rd che sia sotto alla linea di mercato
                    //se la leva è sostenibile (ovvero mi sto spostando a destra ma sono ancora sotto la linea) aggiorno leva e Rd è il mio nuovo rendimento 
                    if((Rd - modello.rendimentoRiskFree) / (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) <= leverage + modello.crescitaLevaMaxStepLeader)
                    {
                        
                        leverage = (Rd - modello.rendimentoRiskFree) / (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree);
                        rendimento = Rd;
                        Console.WriteLine("B");

                    }
                    else
                    //se anche incrementando la leva non riesco a stare sotto la linea, vuol dire che aggiorno lo stesso la leva e 
                    // il nuovo rendimento non sarà più quello desiderato (Rd) ma quello calcolato con la nuova leva
                    {
                        leverage = leverage + modello.crescitaLevaMaxStepLeader;
                        rendimento = modello.rendimentoRiskFree + (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) * leverage;
                        Console.WriteLine("C");
                    }
                }//end if conctrollo leverage organo di governo
            }
        }//end behaviour

        public void behaviour_follower ()
        {
            if(leverage>odg.maxLeverageOrganoDiGoverno && odg.check_organoGovernoActive==true)
                leverage= leverage - modello.crescitaLevaMaxStepFollower;

            //Rd=rendimento desiderato dalla banca che vorrebbe raggiungere
            Rd = rendimento + modello.crescitaRendimentoMaxStepFollower;
            Console.WriteLine("{0}", this.ToString());

            //la banca vede se tale rendimento è sostenibile
            //se è sostenibile allora aggiorna il rendimento
            if(Rd <= modello.rendimentoRiskFree + (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) * leverage)
            {
                rendimento = Rd;

            }
            else
            {
                //L'aumento della leva può essere fatto solo entro un certo limite
                //if((leverage+modello.crescitaLevaMaxStep<modello.maxLeverageBank) ||
                //        (leverage+modello.crescitaLevaMaxStep<modello.maxLeverageOrganoDiGoverno &&
                //         modello.check_organoGovernoActive))
                if(((leverage+modello.crescitaLevaMaxStepFollower)<Math.Min(modello.maxLeverageBankFollower, odg.maxLeverageOrganoDiGoverno) && odg.check_organoGovernoActive) ||
                ((leverage+modello.crescitaLevaMaxStepFollower)<modello.maxLeverageBankFollower) && !odg.check_organoGovernoActive)
                {
                    //altrimenti ricalcolo leva per poterla incrementare in maniera tale da avere un Rd che sia sotto alla linea di mercato
                    //se la leva è sostenibile (ovvero mi sto spostando a destra ma sono ancora sotto la linea) aggiorno leva e Rd è il mio nuovo rendimento 
                    if((Rd - modello.rendimentoRiskFree) / (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) <= leverage + modello.crescitaLevaMaxStepFollower)
                    {
                        leverage = (Rd - modello.rendimentoRiskFree) / (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree);
                        rendimento = Rd;
                    }
                    else
                    //se anche incrementando la leva non riesco a stare sotto la linea, vuol dire che aggiorno lo stesso la leva e 
                    // il nuovo rendimento non sarà più quello desiderato (Rd) ma quello calcolato con la nuova leva
                    {
                        leverage = leverage + modello.crescitaLevaMaxStepFollower;
                        rendimento = modello.rendimentoRiskFree + (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) * leverage;
                    }
                }//end if conctrollo leverage
            }
        }//end behaviour

        public void behaviour_locali ()
        {
            if(leverage>odg.maxLeverageOrganoDiGoverno && odg.check_organoGovernoActive==true)
                leverage= leverage - modello.crescitaLevaMaxStepLocali;

            //Rd=rendimento desiderato dalla banca che vorrebbe raggiungere
            Rd = rendimento + modello.crescitaRendimentoMaxStepLocali;
            Console.WriteLine("{0}", this.ToString());

            //la banca vede se tale rendimento è sostenibile
            //se è sostenibile allora aggiorna il rendimento
            if(Rd <= modello.rendimentoRiskFree + (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) * leverage)
            {
                rendimento = Rd;
            }
            else
            {
                //L'aumento della leva può essere fatto solo entro un certo limite
                //if((leverage+modello.crescitaLevaMaxStep<modello.maxLeverageBank) ||
                //        (leverage+modello.crescitaLevaMaxStep<modello.maxLeverageOrganoDiGoverno &&
                //         modello.check_organoGovernoActive))
                if(((leverage+modello.crescitaLevaMaxStepLocali)<Math.Min(modello.maxLeverageBankLocali, odg.maxLeverageOrganoDiGoverno) && odg.check_organoGovernoActive) ||
                ((leverage+modello.crescitaLevaMaxStepLocali)<modello.maxLeverageBankLocali) && !odg.check_organoGovernoActive)
                {
                    //altrimenti ricalcolo leva per poterla incrementare in maniera tale da avere un Rd che sia sotto alla linea di mercato
                    //se la leva è sostenibile (ovvero mi sto spostando a destra ma sono ancora sotto la linea) aggiorno leva e Rd è il mio nuovo rendimento 
                    if((Rd - modello.rendimentoRiskFree) / (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) <= leverage + modello.crescitaLevaMaxStepLocali)
                    {
                        leverage = (Rd - modello.rendimentoRiskFree) / (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree);
                        rendimento = Rd;
                    }
                    else
                    //se anche incrementando la leva non riesco a stare sotto la linea, vuol dire che aggiorno lo stesso la leva e 
                    // il nuovo rendimento non sarà più quello desiderato (Rd) ma quello calcolato con la nuova leva
                    {
                        leverage = leverage + modello.crescitaLevaMaxStepLocali;
                        rendimento = modello.rendimentoRiskFree + (modello.rendimentoMercatoAttuale - modello.rendimentoRiskFree) * leverage;
                    }
                }//end if conctrollo leverage
            }
        }//end behaviour

        public override String ToString ()
        {
            String ris = id + "\t";
            ris += type + "\t";
            ris += Math.Round(rendimento, 2) + "\t";
            ris += Math.Round(leverage,2) + "\t";
            return ris + "\n";
        }
    }
}
